package edu.snake.implement.controller.general;


import edu.snake.core.controller.ArenaController;
import edu.snake.core.controller.CharacterController;
import edu.snake.core.controller.GameEngine;
import edu.snake.core.model.Character;
import edu.snake.core.model.Character.CharacterName;
import edu.snake.core.view.ViewFactory;
import edu.snake.implement.ConfigConstant;
import edu.snake.implement.controller.character.BaseCharacterController;
import edu.snake.implement.controller.character.SnakeController;
import edu.snake.implement.controller.inputInterface.MouseController;
import edu.snake.implement.factory.ArenaControllerFabric;
import edu.snake.implement.model.other.ScoreModel;
import edu.snake.implement.view.View;
import edu.snake.implement.view.ViewArena;
import edu.snake.implement.view.ViewRenderFactorySwing;

import java.util.ArrayList;
import java.util.List;

import static edu.snake.implement.factory.CharacterControllerFactory.createFrogController;
import static edu.snake.implement.factory.CharacterControllerFactory.createSnakeController;

public class GameEngineImpl implements GameEngine {


    private List<CharacterController> characterControllerList;
    ArenaController arenaController;
    ViewArena viewArena;
    ScoreModel scoreModel;
    View view;

    public GameEngineImpl() {
        initGameEngine();
    }

    private void initGameEngine() {
        ViewFactory viewFactory = new ViewRenderFactorySwing();
        view = viewFactory.getView(this);
    }

    @Override
    public void createCharacter(CharacterName CharacterName/*ToDo What is parameter better Class? String? other???*/) {
        BaseCharacterController controller = createFrogController(arenaController, this);
        characterControllerList.add(controller);
        controller.start();
    }

    @Override
    public void killCharacter(Character character) {
        CharacterController removeController = null;
        for (CharacterController controller : characterControllerList) {
            if (character.equals(controller.getModel())) {
                removeController = controller;
                break;
            }
        }
        if (removeController != null) {
            removeController.stop();
            characterControllerList.remove(removeController);
            arenaController.setToArena(character.getPosition(), null);
        }
        if (arenaController.checkFreeSpace()) {
            createCharacter(null);
        }
    }

    //region Score getter and setter
    @Override
    public void incrementScore(int score) {
        scoreModel.incrementCount(score);

    }

    @Override
    public int getScore() {
        return scoreModel.getCount();
    }
    //endregion

    //region Treads control
    public void pauseThreads() {
        for (CharacterController characterController : characterControllerList) {
            if (characterController.isRunning()) {
                characterController.stop();
            } else {
                characterController.start();
            }

        }
    }

    public void startThreads() {
        for (CharacterController characterController : characterControllerList) {
            characterController.start();
        }
    }

    public void stopThreads() {
        for (CharacterController characterController : characterControllerList) {
            characterController.stop();
        }
    }
    //endregion

    @Override
    public void startGame() {
        arenaController = ArenaControllerFabric.getArena();
        characterControllerList = new ArrayList<CharacterController>();

        int j = ConfigConstant.snakeSize;

        SnakeController snakeController = createSnakeController(arenaController, j, this);
        characterControllerList.add(snakeController);

        for (int i = 0; i < ConfigConstant.frogCount; i++) {
            characterControllerList.add(createFrogController(arenaController, this));
        }

        this.arenaController.getModel().addActionListener(view.getArenaView()); //todo refactor
        viewArena = view.getArenaView();
        viewArena.addMouseListener(new MouseController(snakeController));

        scoreModel = new ScoreModel();
        scoreModel.addActionListener(view.getScoreCountTextLabel());
        scoreModel.setCount(0);
        startThreads();
    }

    @Override
    public void stopGame() {
        stopThreads();
        viewArena.gameOver();
        arenaController = null;
        characterControllerList = null;

        view.getEndButton().setVisible(false);
        view.getStartButton().setVisible(true);
        view.getPauseButton().setVisible(false);
    }

    @Override
    public List<CharacterController> getCharacterAllController() {
        return characterControllerList;
    }

/*    @Override
    public ArenaController getArenaController() {
        return arenaController;
    }*/
}
